import React, { useState, useEffect } from 'react';
import { Tag, message } from 'antd';
import { connect, Dispatch } from 'umi';
import { PageContainer } from '@ant-design/pro-layout';
import ProCard from '@ant-design/pro-card';
import { JOB_INIT, LIST_JOB, ADD_JOB, UPDATE_JOB, DELETE_JOB, PAUSE_JOB, RESUME_JOB, RUN_JOB, JOB_UNMOUNT } from '@/actions/schedule';
import AGrid, { AGridButtonCallBackModel } from '@/components/SelfComp/AGrid';
import { ConnectState } from '@/models/connect';
import { DataItem, FlagEnum } from '@/types/global';
import { JobItem } from '@/types/schedule';
import { getItemValue } from '@/utils/commons';
import ScheduleQueryForm from './components/JobQueryForm';
import AddJobModal from './components/AddJobModal';
import UpdateJobModal from './components/UpdateJobModal';

interface JobListProps {
  dispatch: Dispatch;
  jobList: JobItem[],
  total: number,
  loading: boolean;
  pageSize: number;
  addLoading: boolean;
  updateLoading: boolean;
  jobStatusData: DataItem[];
  jobConcurrentData: DataItem[];
  jobMisfirePolicyData: DataItem[];
}

const EMPTY: JobItem = {
  jobId: '',
  jobGroup: '',
  jobName: '',
  invokeTarget: '',
  jobDesc: '',
  cronExpression: '',
  jobStatus: '',
  concurrent: '',
  misfirePolicy: '',
  startDateTime: '',
  prevFireDateTime: '',
  nextFireDateTime: '',
  triggerGroup: '',
  triggerName: '',
}

/**
 * 定时任务管理，用于配置定时任务，启停任务
 */
const ScheduleList: React.FC<JobListProps> = (props) => {
  // 新增弹窗
  const [addModalVisible, setAddModalVisible] = useState<boolean>(false);
  const [jobFormData, setJobFormData] = useState<JobItem>(EMPTY);
  const [updateModalVisible, setUpdateModalVisible] = useState<boolean>(false);
  const [selectedRows, setSelectedRows] = useState<JobItem[]>([]);
  const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
  const [queryParam, setQueryParam] = useState<JobItem>();
  // 默认为10
  const [pageSize, setPageSize] = useState<number>(10);
  const [flag, setFlag] = useState<FlagEnum>('edit');

  useEffect(() => {
    console.info('ScheduleList.useEffect');
    // 查询本页面需所有参数
    const { dispatch } = props;
    dispatch(JOB_INIT({}));
    return () => {
      dispatch(JOB_UNMOUNT({}));
    }
  }, []);

  const columns = [
    {
      title: '任务分组',
      dataIndex: 'jobGroup',
      width: 200,
      ellipsis: true
    },
    {
      title: '任务名称',
      dataIndex: 'jobName',
      width: 200,
      ellipsis: true
    },
    {
      title: '任务执行bean',
      dataIndex: 'invokeTarget',
      width: 220
    },
    {
      title: '任务描述',
      dataIndex: 'jobDesc',
      width: 250,
      ellipsis: true
    },
    {
      title: 'Cron时间表达式',
      dataIndex: 'cronExpression',
      width: 140
    },
    {
      title: '任务状态',
      dataIndex: 'jobStatus',
      width: 100,
      render: (_text: string, record: JobItem, _index: number) => {
        const { jobStatusData } = props;
        const { jobStatus } = record;
        const value = getItemValue(jobStatusData, jobStatus);
        return (
          jobStatus === '0' ? <Tag color="success">{value}</Tag> : <Tag color="error">{value}</Tag>
        );
      },
    },
    {
      title: '是否允许并发执行',
      dataIndex: 'concurrent',
      width: 160,
      render: (_text: string, record: JobItem, _index: number) => {
        const { jobConcurrentData } = props;
        const { concurrent } = record;
        return (
          getItemValue(jobConcurrentData, concurrent)
        );
      },
    },
    {
      title: 'misfire处理策略',
      dataIndex: 'misfirePolicy',
      width: 160,
      render: (text: string, record: JobItem, index: number) => {
        const { jobMisfirePolicyData } = props;
        const { misfirePolicy } = record;
        return (
          getItemValue(jobMisfirePolicyData, misfirePolicy)
        );
      },
    },
    {
      title: '任务开始时间',
      dataIndex: 'startDateTime',
      width: 160
    },
    {
      title: '上一次执行时间',
      dataIndex: 'prevFireDateTime',
      width: 160
    },
    {
      title: '下一次执行时间',
      dataIndex: 'nextFireDateTime',
      width: 160
    },
    {
      title: '触发器分组',
      dataIndex: 'triggerGroup',
      width: 150,
      ellipsis: true
    },
    {
      title: '触发器名称',
      dataIndex: 'triggerName',
      width: 150,
      ellipsis: true
    }
  ];

  const openAddJobModal = () => {
    setAddModalVisible(true);
  }

  const handleAddModalOk = async (record: JobItem) => {
    console.log(record);
    const { dispatch } = props;
    const res = await dispatch(ADD_JOB(record));
    console.info(res);
    if (res) {
      setAddModalVisible(false);
      fetchAllJob(1, pageSize, queryParam);
    }
  }

  const handleAddModalCancel = () => {
    setAddModalVisible(false);
  };

  /**
   * 修改参数，打开参数修改窗口
   */
  const openUpdateJobModal = (record: JobItem[], flag: FlagEnum) => {
    // 表格选中内容
    // console.info('openUpdateJobModal');
    // console.info(record);
    const row = record[0];
    const jobFormData = {
      ...row,
    };
    setJobFormData(jobFormData);
    setFlag(flag);
    setUpdateModalVisible(true);
  }

  /**
   * 更新面板的确定事件
   * @param {*} record 更新表单
   */
  const handleUpdateModalOk = async (record: JobItem) => {
    // console.log('handleUpdateModalOk');
    // console.log(record);
    // console.info(jobFormData);
    if (flag === 'edit') {
      const { dispatch } = props;
      const res = await dispatch(UPDATE_JOB(record));
      console.info(res);
      if (res) {
        setJobFormData(EMPTY);
        setUpdateModalVisible(false);
        fetchAllJob(1, pageSize, queryParam);
      }
    } else {
      setJobFormData(EMPTY);
      setUpdateModalVisible(false);
    }
  }

  const handleUpdateModalCancel = () => {
    setJobFormData(EMPTY);
    setUpdateModalVisible(false);
  };

  /**
   * 根据条件分页查询表格数据
   * @param {*} record 条件
   */
  const handleFetchJob = (record: JobItem) => {
    // console.log(record);
    const queryParam = {
      ...record
    };
    // 查询条件保存起来，方便点击页码时使用
    // setState回调方法，保证先更新state
    setQueryParam(queryParam);
    fetchAllJob(1, pageSize, queryParam);
  }

  /**
   * 页码改变的回调，参数是改变后的页码及每页条数
   * @param pageNum 改变后的页码，上送服务器端
   * @param pageSize 每页数据条数
   */
  const onPageNumAndSizeChange = (pageNum: number, pageSize: number) => {
    // console.log(pageNum, pageSize);
    setPageSize(pageSize);
    fetchAllJob(pageNum, pageSize);
  };

  /**
   * 分页查询系统参数信息
   * @param {*} pageNum 页码
   * @param {*} pageSize 每页记录条数
   */
  const fetchAllJob = (pageNum: number, pageSize: number, queryParam?: JobItem) => {
    setPageSize(pageSize);
    fetchAllJob0(pageNum, pageSize, queryParam);
  }

  /**
   * 分页查询系统参数信息
   * @param {*} pageNum 页码
   * @param {*} pageSize 每页记录条数
   */
  const fetchAllJob0 = (pageNum: number, pageSize: number, queryParam?: JobItem) => {
    const { dispatch } = props;
    dispatch(LIST_JOB({
      ...queryParam,
      pageSize,
      pageNum
    }));
  }

  /**
   * 处理按钮点击回调事件
   * @param {*} payload 数据包
   */
  const handleBtnCallBack = (callBackModel: AGridButtonCallBackModel<JobItem>) => {
    console.log('handleBtnCallBack');
    console.log(callBackModel);
    // btn 按钮
    // keys 表格勾选数组
    const { code } = callBackModel;
    // 新增
    if (code === 'add') {
      openAddJobModal();
      return;
    }
    // 修改
    if (code === 'edit') {
      const { rows } = callBackModel;
      openUpdateJobModal(rows, 'edit');
      return;
    }
    // 删除
    if (code === 'delete') {
      const { keys } = callBackModel;
      // 调用删除服务，删除勾选数据
      deleteJobs(keys);
      return;
    }
    // 查看
    if (code === 'view') {
      const { rows } = callBackModel;
      openUpdateJobModal(rows, 'view');
      return;
    }
    // 运行一次任务
    if (code === 'run') {
      const { rows } = callBackModel;
      const record = rows[0];
      const { jobStatus } = record;
      if (jobStatus !== '0') {
        message.error("任务状态异常，不允许运行");
        return;
      }
      runOnceJob(rows[0]);
      return;
    }
    // 暂停任务
    if (code === 'pause') {
      const { rows } = callBackModel;
      const record = rows[0];
      const { jobStatus } = record;
      if (jobStatus !== '0') {
        message.error("任务状态异常，不允许暂停");
        return;
      }
      pauseJob(rows[0]);
      return;
    }
    // 恢复任务
    if (code === 'resume') {
      const { rows } = callBackModel;
      const record = rows[0];
      const { jobStatus } = record;
      if (jobStatus !== '1') {
        message.error("任务状态异常，不允许恢复");
        return;
      }
      resumeJob(rows[0]);
      return;
    }
  }

  const deleteJobs = async (keys: React.Key[]) => {
    const { dispatch } = props;
    const res = await dispatch(DELETE_JOB(keys));
    if (res) {
      fetchAllJob(1, pageSize, queryParam);
    }
  }

  const runOnceJob = async (record: JobItem) => {
    // console.log(record);
    const { dispatch } = props;
    const res = await dispatch(RUN_JOB(record));
    // console.info(res);
    if (res) {
      fetchAllJob(1, pageSize, queryParam);
    }
  }

  const pauseJob = async (record: JobItem) => {
    console.log(record);
    const { dispatch } = props;
    const res = await dispatch(PAUSE_JOB(record));
    // console.info(res);
    if (res) {
      fetchAllJob(1, pageSize, queryParam);
    }
  }

  const resumeJob = async (record: JobItem) => {
    // console.log(record);
    const { dispatch } = props;
    const res = await dispatch(RESUME_JOB(record));
    // console.info(res);
    if (res) {
      fetchAllJob(1, pageSize, queryParam);
    }
  }

  /**
   * 表格勾选回调函数
   * @param {*} keys 指定选中项的 key 数组
   * @param {*} rows 表格选中数据集合
   */
  const onSelectRow = (keys: React.Key[], rows: JobItem[]) => {
    setSelectedRowKeys(keys);
    setSelectedRows(rows);
  };

  const code = 'schedule-list';
  const { jobList, loading, total, addLoading, updateLoading, jobStatusData, jobConcurrentData, jobMisfirePolicyData } = props;
  const rowKey = (record: JobItem) => record.jobId;
  const pkField = 'jobId';

  return (
    <PageContainer>
      <ProCard title="定时任务列表" headerBordered>
        <ScheduleQueryForm
          colon={false}
          onSubmit={handleFetchJob}
          loading={loading}
          jobStatusData={jobStatusData}
        />
        <AGrid
          code={code}
          btnCallBack={handleBtnCallBack}
          columns={columns}
          rowKey={rowKey}
          dataSource={jobList}
          total={total}
          loading={loading}
          onSelectRow={onSelectRow}
          pkField={pkField}
          actionColumnWidth={200}
          actionColumnFixed={'right'}
          scroll={{x:2200}}
          onPageNumAndSizeChange={onPageNumAndSizeChange}
        />
      </ProCard>
      {
        !addModalVisible ? null :
        <AddJobModal
          colon={false}
          modalTitle='新增定时任务'
          modalWidth={1000}
          modalVisible={addModalVisible}
          loading={addLoading}
          jobStatusData={jobStatusData}
          jobConcurrentData={jobConcurrentData}
          jobMisfirePolicyData={jobMisfirePolicyData}
          onHandlerOK={handleAddModalOk}
          onHandlerCancel={handleAddModalCancel}
        />
      }
      {
        !updateModalVisible ? null :
        <UpdateJobModal
          colon={false}
          modalWidth={1000}
          modalVisible={updateModalVisible}
          modalTitle=''
          flag={flag}
          loading={updateLoading}
          formData={jobFormData}
          jobStatusData={jobStatusData}
          jobConcurrentData={jobConcurrentData}
          jobMisfirePolicyData={jobMisfirePolicyData}
          onHandlerOK={handleUpdateModalOk}
          onHandlerCancel={handleUpdateModalCancel}
        />
      }
    </PageContainer>
  );
}

export default connect(({ schedules: { rows, ...res }, systems, loading }: ConnectState) => ({
  ...res,
  jobList: rows,
  jobStatusData: systems.jobStatusData,
  jobConcurrentData: systems.jobConcurrentData,
  jobMisfirePolicyData: systems.jobMisfirePolicyData,
  loading: loading.effects['schedules/fetchAllJob'],
  addLoading: loading.effects['schedules/addJob'],
  updateLoading: loading.effects['schedules/updateJob']
}))(ScheduleList);